package markdown;


import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;

import java.time.LocalDateTime;
import java.util.List;
import java.util.Map;


public class MarkdownEngine {


    public String parseToMarkdown(String title,String content) throws JsonProcessingException {
        StringBuilder std = new StringBuilder();
        std.append(MarkBlock.H1.getContent()).append(title).append("\n");
        ObjectMapper objectMapper = new ObjectMapper();
        List<Map<String,Object>> list = objectMapper.readValue(content, List.class);
        for(Map map:list){
            std.append(parseData(map));
            std.append("\n");
        }
        return std.toString();
    }

    private String parseData(Map map) throws JsonProcessingException {
        ObjectMapper objectMapper = new ObjectMapper();
        String type = (String)map.get("type");
        String data = objectMapper.writeValueAsString(map.get("data"));
        String res;
        switch (type){
            case "header":
                res = parseHeading(data);
                break;
            case "list":
                res = parseList(data);
                break;
            case "image":
                res = parseImage(data);
                break;
            case "quote":
                res = parseQuote(data);
                break;
            case "table":
                res = parseTable(data);
                break;
            case "raw":
                res = parseRaw(data);
                break;
            case "paragraph":
                res = parseParagraph(data);
                break;
            case "code":
                res = parseCode(data);
                break;
            default:
                res = "解析失败,暂不支持该类型\n";
        }
        return res;
    }


    private String parseHeading(String data) throws JsonProcessingException {
        ObjectMapper objectMapper = new ObjectMapper();
        Map<String,Object> map = objectMapper.readValue(data, Map.class);
        Integer level = (Integer) map.get("level");
        String text = (String)map.get("text");
        String replace = text.replace("\\", "");
        if(level==1){
            return MarkBlock.H1.getContent()+replace;
        }else if(level==2){
            return MarkBlock.H2.getContent()+replace;
        }else if(level==3){
            return MarkBlock.H3.getContent()+replace;
        }else if(level==4){
            return MarkBlock.H4.getContent()+replace;
        }else{
            return MarkBlock.H5.getContent()+replace;
        }
    }

    private String parseList(String data) throws JsonProcessingException {
        ObjectMapper objectMapper = new ObjectMapper();
        EditorList editorList = objectMapper.readValue(data, EditorList.class);
        return parseItems(editorList.getItems(), editorList.getStyle());
    }

    private String parseItems(Item[] items,String type){
        String blank = "  ";
        StringBuilder res = new StringBuilder();
        if(type.equals("unordered")){
            for(Item item:items){
                res.append(MarkBlock.UN_ORDER_LIST.getContent()).append(item.getContent()).append("\n");
                if(item.getItems().length!=0){
                    res.append(blank).append(parseItems(item.getItems(),type));
                }
            }
        }else if(type.equals("ordered")){
            for(int i=1;i<=items.length;i++){
                Item item = items[i-1];
                res.append(i+". ").append(item.getContent()).append("\n");
                if(item.getItems().length!=0){
                    res.append(blank).append(blank).append(parseItems(item.getItems(),type));
                }
            }
        }else{
            for(Item item:items){
                res.append((Boolean) item.getMeta().get("checked")?MarkBlock.CHECK_BOX_ONE.getContent():MarkBlock.CHECK_BOX.getContent()).append(item.getContent()).append("\n");
                if(item.getItems().length!=0){
                    res.append(blank).append(parseItems(item.getItems(),type));
                }
            }
        }
        String str = res.toString();
        return str.replace("//","");
    }

    private String parseImage(String data) throws JsonProcessingException {
        ObjectMapper objectMapper = new ObjectMapper();
        EditorImage editorImage = objectMapper.readValue(data, EditorImage.class);
        String url = (String)editorImage.getFile().get("url");
        String imageMd = MarkBlock.IMAGE.getContent().replace("alt text", LocalDateTime.now().toString()).replace("url",url);
        return imageMd;
    }

    private String parseQuote(String data) throws JsonProcessingException {
        ObjectMapper objectMapper = new ObjectMapper();
        Map<String,Object> map = objectMapper.readValue(data, Map.class);
        String caption = (String)map.get("text");
        StringBuilder res = new StringBuilder();
        res.append(MarkBlock.QUOTE.getContent()).append(caption);
        return res.toString();
    }

    public String parseTable(String data) throws JsonProcessingException {
        ObjectMapper objectMapper = new ObjectMapper();
        Map<String,Object> map = objectMapper.readValue(data, Map.class);
        List<List<String>> content = (List<List<String>>) map.get("content");
        int row = content.size();
        int col = content.get(0).size();
        Boolean bool = (Boolean) map.get("withHeadings");
        StringBuilder res = new StringBuilder();
        if(bool){
            for(int i=0;i<row;i++){
                if(i==1){
                    res.append(MarkBlock.TABLE_HEAD.getContent().repeat(col)).append(MarkBlock.TABLE_END.getContent()).append("\n");
                }
                for(String str:content.get(i)){

                    res.append(MarkBlock.TABLE_START.getContent()).append(str).append(" ");
                }
                res.append(MarkBlock.TABLE_END.getContent()).append("\n");
            }
        }else{
            res.append(MarkBlock.TABLE_START.getContent().repeat(col)).append(MarkBlock.TABLE_END.getContent()).append("\n");
            res.append(MarkBlock.TABLE_HEAD.getContent().repeat(col)).append(MarkBlock.TABLE_END.getContent()).append("\n");
            for(int i=0;i<row;i++){
                for(String str:content.get(i)){
                    res.append(MarkBlock.TABLE_START.getContent()).append(str).append(" ");
                }
                res.append(MarkBlock.TABLE_END.getContent()).append("\n");
            }
        }
        return res.toString();
    }

    public String parseCode(String data) throws JsonProcessingException {
        ObjectMapper objectMapper = new ObjectMapper();
        Map<String,Object> map = objectMapper.readValue(data, Map.class);
        String language = (String)map.get("language");
        String code = (String)map.get("code");
        String replace = MarkBlock.CODE_BLOCK.getContent().replace("language", language).replace("code", code);
        return replace;
    }

    public String parseRaw(String data) throws JsonProcessingException {
        ObjectMapper objectMapper = new ObjectMapper();
        Map<String,Object> map = objectMapper.readValue(data, Map.class);
        String html = (String)map.get("html");
        return html;
    }

    private String parseParagraph(String data) throws JsonProcessingException {
        ObjectMapper objectMapper = new ObjectMapper();
        Map<String,Object> map = objectMapper.readValue(data, Map.class);
        String text = (String) map.get("text");
        String replace = text.replace("\\", "");
        return replace;
    }



}

